package MetaClassifierAlgorithms;


import Definitions.GraphClass;
import Global.GlobalClass;
import Sampling.SamplingAbstractClass;
import Utility.WorkerUtilityClass;

public class LocalAlphaMaxBasedMetaClassifierClass  extends MetaClassifierAbstractClass {

	LocalAlphaMaxBasedMetaClassifierClass(String metaClassifierName, GraphClass graph,
			GlobalClass global, SamplingAbstractClass currentSampling, double[][][] probabilityDistributionMatrixForTheClassifiers) {
		
		super(metaClassifierName, graph, global, currentSampling, probabilityDistributionMatrixForTheClassifiers);
		// TODO Auto-generated constructor stub
	}
	public void metaClassify()
	{
		double weightedMergedFormOfTheProbabilitiesPerClassBasis[];
		
		//double metaResultProbabilitiesPerClassBasis[] = new double[GlobalClass.classSize];
		double[][] weightsToBeUsed = currentSampling.getLocalAlphaMatrixForThisFold();
		//double[][] weightsToBeUsed = new double[weightsToBeUsedTemp.length][weightsToBeUsedTemp[0].length]; //= currentSampling.getLocalAlphaMatrixForThisFold();
		
		double[] globalWeightsToBeUsed = new double[weightsToBeUsed.length];		
		
		int metaClassLabelEstimated;
		double sumOfTheLocalAlphaWeigthsForTheNode;
		
		//WorkerUtilityClass.initializeTwoDimensionalArray(weightsToBeUsed, 5.0);
		
		for(int j=0; j<probabilityDistributionMatrixForTheClassifiers.length; j++)
			globalWeightsToBeUsed[j] = Utility.WorkerUtilityClass.getAverage(weightsToBeUsed[j]);
		
		boolean isAllGlobalAlphasNotZero = checkIfAllGlobalAlphasNotZero(globalWeightsToBeUsed);		
		
		int[] numberOfLocalAlphaUsagePerCls = new int[probabilityDistributionMatrixForTheClassifiers.length];
		int[] numberOfGlobalAlphaUsagePerCls = new int[probabilityDistributionMatrixForTheClassifiers.length];
		int[] maxMethodLikeUsagePerCls = new int[probabilityDistributionMatrixForTheClassifiers.length];
		
		//double[] degreeListOfTheNodes = graph.getPropertiesOfTheGraphWithRespectToEdgeType().get(0).degreeDistributionRelatedProps.getDegreeListOfNodes();
		
		//double degreeOfTheNode;
		//double degreeThreshold = graph.getPropertiesOfTheGraphWithRespectToEdgeType().get(0).degreeDistributionRelatedProps.getAverageDegreeOfNodes();
		
		for(int nodeNo=0; nodeNo<probabilityDistributionMatrixForTheClassifiers[0].length; nodeNo++)
		{
			sumOfTheLocalAlphaWeigthsForTheNode = 0.0;
			
			//degreeOfTheNode = degreeListOfTheNodes[currentSampling.getTestNodes().get(nodeNo).getOrder()];			
			
			for(int j=0; j<probabilityDistributionMatrixForTheClassifiers.length; j++)
				sumOfTheLocalAlphaWeigthsForTheNode += weightsToBeUsed[j][nodeNo];
				
			//System.out.println("["+j+"]["+nodeNo+"]:"+weightsToBeUsed[j][nodeNo]);
			if(sumOfTheLocalAlphaWeigthsForTheNode!=0 /* && degreeOfTheNode>degreeThreshold*/)
			{
				weightedMergedFormOfTheProbabilitiesPerClassBasis = WorkerUtilityClass.getScalarProductOfTheArray(probabilityDistributionMatrixForTheClassifiers[0][nodeNo], weightsToBeUsed[0][nodeNo]);
				numberOfLocalAlphaUsagePerCls[0]++;

				for(int j=1; j<probabilityDistributionMatrixForTheClassifiers.length; j++)
				{	
					weightedMergedFormOfTheProbabilitiesPerClassBasis = WorkerUtilityClass.mergeTwoDoubleArrays(weightedMergedFormOfTheProbabilitiesPerClassBasis, WorkerUtilityClass.getScalarProductOfTheArray(probabilityDistributionMatrixForTheClassifiers[j][nodeNo], weightsToBeUsed[j][nodeNo]));
					numberOfLocalAlphaUsagePerCls[j]++;
				}
			}
			else if(isAllGlobalAlphasNotZero/* && degreeOfTheNode>degreeThreshold*/)
			{
				weightedMergedFormOfTheProbabilitiesPerClassBasis = WorkerUtilityClass.getScalarProductOfTheArray(probabilityDistributionMatrixForTheClassifiers[0][nodeNo], globalWeightsToBeUsed[0]);
				numberOfGlobalAlphaUsagePerCls[0]++;

				for(int j=1; j<probabilityDistributionMatrixForTheClassifiers.length; j++)
				{	
					weightedMergedFormOfTheProbabilitiesPerClassBasis = WorkerUtilityClass.mergeTwoDoubleArrays(weightedMergedFormOfTheProbabilitiesPerClassBasis, probabilityDistributionMatrixForTheClassifiers[j][nodeNo]);
					numberOfGlobalAlphaUsagePerCls[j]++;
				}
			}
			else
			{
				weightedMergedFormOfTheProbabilitiesPerClassBasis = probabilityDistributionMatrixForTheClassifiers[0][nodeNo];
				maxMethodLikeUsagePerCls[0]++;

				for(int j=1; j<probabilityDistributionMatrixForTheClassifiers.length; j++)
				{
					weightedMergedFormOfTheProbabilitiesPerClassBasis = WorkerUtilityClass.mergeTwoDoubleArrays(weightedMergedFormOfTheProbabilitiesPerClassBasis, probabilityDistributionMatrixForTheClassifiers[j][nodeNo]);
					maxMethodLikeUsagePerCls[j]++;
				}

			}

			metaClassLabelEstimated = WorkerUtilityClass.findMaxIndexForTheGivenVector(weightedMergedFormOfTheProbabilitiesPerClassBasis);
			metaClassLabelEstimated = metaClassLabelEstimated % global.classSize; 

			currentSampling.setClassLabelEstimated(currentSampling.getTestNodes().get(nodeNo), metaClassLabelEstimated);			
		}		
		
		WorkerUtilityClass.printArray(numberOfLocalAlphaUsagePerCls, "Local Alpha MAX Usage Stats:");
		WorkerUtilityClass.printArray(numberOfGlobalAlphaUsagePerCls, "Global Alpha MAX Usage Stats:");
		WorkerUtilityClass.printArray(maxMethodLikeUsagePerCls, "MAX Method like Usage Stats:");
	}

	boolean checkIfAllGlobalAlphasNotZero(double[] globalWeightsToBeUsed)
	{
		for(int i=0; i<globalWeightsToBeUsed.length; i++)			
			if(globalWeightsToBeUsed[i]==0)
				return false;
		return true;
	}
}
